package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
	flag "github.com/spf13/pflag"
)

func main() {
	cfgFile := flag.StringP("config", "c", "", "")
	flag.Parse()
	if *cfgFile == "" {
		fmt.Printf("error, must provide config")
		os.Exit(-1)
	}
	config, err := loadConfig(*cfgFile)
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("failed load config")
	}

	mqtt, err := NewMQTTSender(config.MQTTConfig)
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("failed create mqtt")
	}

	sender := &sender{
		prefix:     config.MQTTConfig.TopicPrefix,
		qos:        config.MQTTConfig.Qos,
		timeout:    config.MQTTConfig.PublishTimeout.ToDuration(),
		mqttSender: mqtt,
	}
	handler := makeHandler(sender)

	receiver, err := NewTCPReceiver(config.TCPReceiverConfig, handler)
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("failed create tcp receiver")
	}
	err = receiver.Open()
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("failed open tcp receiver")
	}
	err = receiver.Start()
	if err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("failed start tcp receiver")
	}

	ch := make(chan int)
	<-ch
}

// Sender sender interface
type Sender interface {
	Send(key string, data []byte) error
}

type sender struct {
	prefix     string
	qos        int
	timeout    time.Duration
	mqttSender *MQTTSender
}

func (s *sender) Send(key string, data []byte) error {
	topic := fmt.Sprintf("%s/%s", s.prefix, key)
	return s.mqttSender.Send(topic, s.qos, data, s.timeout)
}

func encodeMac(mac string) (string, error) {
	mac = strings.Replace(mac, ":", "", -1)
	mac = strings.ToUpper(mac)
	return mac, nil
}

func makeHandler(sender Sender) func(conn net.Conn) {
	return func(conn net.Conn) {
		for {
			data, err := bufio.NewReader(conn).ReadString('\n')
			if err != nil {
				log.WithFields(log.Fields{"err": err}).Error("")
				conn.Close()
				return
			}
			log.WithFields(log.Fields{"data": data}).Info("received data")
			bytes := []byte(data)
			var m T6006
			err = json.Unmarshal(bytes, &m)
			if err != nil {
				log.WithFields(log.Fields{"err": err}).Error("error parsing received data")
				continue
			}
			mac := m.Mac
			tmac, err := encodeMac(mac)
			if err != nil {
				log.WithFields(log.Fields{"err": err, "mac": mac}).Error("error format mac")
			}
			err = sender.Send(tmac, bytes)
			if err != nil {
				log.WithFields(log.Fields{"err": err}).Error("send error")
			} else {
				log.WithFields(log.Fields{"bytes": string(bytes)}).Info("send msg")
			}
		}
	}
}

func loadConfig(path string) (Config, error) {
	f, err := os.Open(path)
	if err != nil {
		return Config{}, err
	}
	defer f.Close() // nolint
	content, err := ioutil.ReadAll(f)
	if err != nil {
		return Config{}, err
	}
	var config Config
	err = json.Unmarshal(content, &config)
	return config, err
}

func init() {
	log.SetLevel(log.DebugLevel)
}
